package priv.abadstring.study.haoke.webapi.interceptor;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

/**
 * RedisCacheInterceptor
 *
 * @author aBadString
 * @date 2021-07-29 17:20:08
 */
@Component
public class RedisCacheInterceptor implements HandlerInterceptor {

    @Autowired
    private RedisTemplate<String,String> redisTemplate;
    private static final Logger LOGGER = LoggerFactory.getLogger(RedisCacheInterceptor.class);


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        // OPTIONS 请求不进行缓存获取
        if (StringUtils.equalsAnyIgnoreCase(request.getMethod(), "OPTIONS")) {
            return true;
        }
        // 非 GET 且 非 GraphQL 请求不进行缓存获取
        if (!StringUtils.equalsIgnoreCase(request.getMethod(), "GET")
                && !StringUtils.equalsIgnoreCase(request.getRequestURI(), "/graphql")) {
            return true;
        }

        String key = createRedisKey(request);
        String value = this.redisTemplate.opsForValue().get(key);
        // 缓存未命中
        if (StringUtils.isEmpty(value)) {
            return true;
        }

        // 缓存命中
        LOGGER.info("[缓存命中] uri=" + request.getRequestURI());
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Headers", "Content-Type,X-Token");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.getWriter().write(value);
        return false;
    }


    private static final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 根据请求的 url 和请求参数生成 key
     */
    public static String createRedisKey(HttpServletRequest request) throws IOException {
        String uri = request.getRequestURI();
        Map<String, String[]> parameters = request.getParameterMap();

        if (parameters.isEmpty()) {
            uri += IOUtils.toString(request.getInputStream(), "UTF-8");
        } else {
            uri += objectMapper.writeValueAsString(request.getParameterMap());
        }

        return "WEB_DATA_" + DigestUtils.md5Hex(uri);
    }
}
